﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AG.Editor.Core.Data;
using System.IO;
using AG.Editor.Core.Publish;
using System.Xml.Linq;
using AG.Editor.Core.Metadata;

namespace AG.Editor.Core
{
    public class AGPublisher
    {
        public void PublishProject(string publishFolder, AGEProject project)
        {
            if (!Directory.Exists(publishFolder))
            {
                Directory.CreateDirectory(publishFolder);
            }

            PublishDataFile(publishFolder, project);

            AGModelPulisher modelPub = new AGModelPulisher();
            string pubModelFolder = Path.Combine(publishFolder, "Models\\");
            for (int index = 0; index < project.Models.Count; index++)
            {
                AGModel model = AGTools.Current.ModelStore.GetModel(project, project.Models[index]);
                modelPub.Publish(project, model, pubModelFolder);
            }

            for (int index = 0; index < project.TextureFonts.Count; index++)
            {
                AGTextureFont font = AGTools.Current.TextureFontStore.LoadTextureFont(project, project.TextureFonts[index]);
                PublishTextureFonts(project, publishFolder, font);
            }
        }

        private void PublishDataFile(string publishFolder, AGEProject project)
        {
            string dataFileName = Path.Combine(publishFolder, "data.xml");
            XDocument xDoc = new XDocument();

            XElement xElement = new XElement("data");
            xDoc.Add(xElement);
            xElement.Add(new XAttribute("project", project.Name));

            XElement xModelCategoryList = new XElement("model-category-list");
            xElement.Add(xModelCategoryList);
            for (int index = 0; index < project.TProject.ModelCategories.Count; index++)
            {
                AGModelCategory category = project.TProject.ModelCategories[index];

                XElement xCagetory = new XElement("category");
                xModelCategoryList.Add(xCagetory);
                xCagetory.Add(new XAttribute("id", category.Id));
                xCagetory.Add(new XAttribute("caption", category.Caption));
            }

            #region model-list
            XElement xModelList = new XElement("model-list");
            xElement.Add(xModelList);
            for (int index = 0; index < project.Models.Count; index++)
            {
                AGModelRef modelRef = project.Models[index];
                XElement xModel = new XElement("model");
                xModelList.Add(xModel);
                
                AGModel model = AGTools.Current.ModelStore.GetModel(project, project.Models[index]);
                xModel.Add(new XAttribute("id", model.Id));
                xModel.Add(new XAttribute("caption", model.Caption));
                xModel.Add(new XAttribute("category-id", model.CategoryId));
            }
            #endregion

            #region terrain-list
            XElement xTerrainList = new XElement("terrain-list");
            xElement.Add(xTerrainList);
            for (int index = 0; index < project.Terrains.Count; index++)
            {
                AGTerrain terrain = project.Terrains[index];
                XElement xTerrain = new XElement("terrain");
                xTerrainList.Add(xTerrain);

                AGModelRef modelRef = project.GetModelRef(terrain.ModelUniqueId);
                AGModel model = AGTools.Current.ModelStore.GetModel(project, modelRef);
                xTerrain.Add(new XAttribute("id", terrain.Id));
                xTerrain.Add(new XAttribute("caption", terrain.Name));
                xTerrain.Add(new XAttribute("foreground", terrain.ForegroundId));
                xTerrain.Add(new XAttribute("background", terrain.BackgroundId));
                xTerrain.Add(new XAttribute("model-id", model.Id));

                for (int tileIndex = 0; tileIndex < terrain.Tiles.Count; tileIndex++)
                {
                    AGTerrainTile tile = terrain.Tiles[tileIndex];
                    XElement xTile = new XElement("tile");
                    xTerrain.Add(xTile);
                    xTile.Add(new XAttribute("id", tile.Id));
                    xTile.Add(new XAttribute("caption", tile.Caption));
                    xTile.Add(new XAttribute("count", tile.Count));
                }
            }
            #endregion

            xDoc.Save(dataFileName);
        }

        private void PublishTextureFonts(AGEProject project, string publishFolder, AGTextureFont tfont)
        {
            string textureFontsFolder = Path.Combine(publishFolder, string.Format("Fonts\\"));
            if (!Directory.Exists(textureFontsFolder))
            {
                Directory.CreateDirectory(textureFontsFolder);
            }
            string textureFontFileFullName = Path.Combine(publishFolder, string.Format("Fonts\\{0}.xml", tfont.Id));

            XDocument xDoc = new XDocument();

            XElement xFont = new XElement("font");
            xDoc.Add(xFont);

            xFont.Add(new XAttribute("id", tfont.Id));
            xFont.Add(new XAttribute("caption", tfont.Caption));
            xFont.Add(new XAttribute("texture", tfont.TextureFile));

            for (int index = 0; index < tfont.CharList.Count; index++)
            {
                AGTextureFontChar fc = tfont.CharList[index];

                XElement xFontChar = new XElement("char");
                xFont.Add(xFontChar);

                xFontChar.Add(new XAttribute("name", fc.CharString));
                xFontChar.Add(new XAttribute("rect", string.Format("{0},{1},{2},{3}", fc.Left, fc.Top, fc.Left + fc.Width, fc.Top + fc.Height)));
            }

            xDoc.Save(textureFontFileFullName);

            // 拷贝资源文件
            string srcTextureFullName = string.Format("{0}{1}", project.GetFolderFonts(), tfont.TextureFile);
            File.Copy(srcTextureFullName, string.Format("{0}\\Fonts\\{1}", publishFolder, tfont.TextureFile), true);
        }
    }
}
